package org.zturn.exhibition.test;
 
import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.zturn.exhibition.util.AESUtil;
import org.zturn.exhibition.util.RSAUtil;

import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
 
/**
 * @ClassName : UtilsTestClass
 * @Description : 工具类测试类
 * @Author : AD
 */
 
@Slf4j
public class UtilsTestClass {
 
    /**
     * 可以将其放入配置文件中进行读取
     * */
    String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDI7HE0aW9ILCMkfoAJYmAG+5RBRhU2Itebf04GUtnYMuR6Rl1GJKec7JKuM/8xSindH4jn6Vz3oARTjbCn4CxjbtQPys5i8VeXxgzzqhE34LY0Rt62Qy8UVS113454DTwZZR9BjmPQSxMaftQHMgeDjXVwLUt0a6CmRiZKOjw8WQIDAQAB";
    String privateKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAMjscTRpb0gsIyR+gAliYAb7lEFGFTYi15t/TgZS2dgy5HpGXUYkp5zskq4z/zFKKd0fiOfpXPegBFONsKfgLGNu1A/KzmLxV5fGDPOqETfgtjRG3rZDLxRVLXXfjngNPBllH0GOY9BLExp+1AcyB4ONdXAtS3RroKZGJko6PDxZAgMBAAECgYBRUHdkKcNypwI188gnhBuu18QhQpa1CRbPBI90ObWWLMqQvcdj6tO2y3t1au+9Z/FXXzrN+IC6apU1p2M2HaB4iPdW+2Vm0DaRN7XJPzBdJqVASYVJ2oWWLWCkG05mS2pAgcMlxV3TLen7iBFKTjgZhdLIal8JYgyi6XWdNlAtAQJBAPjCtpmXuAS9luyXo2ExEauKEC2uC06FeZqgM6u1rTqsqUE5kGpmJ1DiERuOcQxn8i+mlnJ1Urmw8ltMxmnJAiECQQDOxVbjUXWolwRF8lsOeZ9XGGc/45pE7J8DubEV0Ii1RVckMyTkXmgNAupE7Xq9cgNMpNBRUQEDNzSHhA8rqGM5AkBuwWrBac6RtcPLpRwl+s3uPTNE01fPZxgkYy1+Rw5QsG1PUAzfgooAthZ92Wa16lXnJ1mWrmvdp03Qnpc8pDVhAkBoqWD6vV/2D0L9eNh4cj2iY1rX7whGfRNcWmD1rtGUF94tF6pD4jl+5Ivaie6H+C8NW5uKnZsKmqX/NmxLZ/eZAkBDXRX7YgMG4PLXcjPT4ot6DEJDjuSVb1LhwucL6QFFYhZloH3/9XQS3T9XB/2F61tdh5Jd3FaCD7WeXJCzW+64";
 
 
    /**
     * Description: 测试获取密钥的方法
    */
    @Test
    public void testGetASK() throws Exception {
        // AES密钥
        String aesKey = AESUtil.getAESKey(16);
        System.out.println("aesKey = " + aesKey);
        // AES Base64类型密钥
        String base64AesKey = AESUtil.generateRandomAesKeyWithBase64();
        System.out.println("base64AesKey = " + base64AesKey);
 
        //RSA 私钥公钥
        Map map = RSAUtil.generateRandomToBase64Key();
        System.out.println("map.get(\"privateKey\") = " + map.get("privateKey"));
        System.out.println("map.get(\"publicKey\") = " + map.get("publicKey"));
 
    }
 
 
    /**
     * Description: post请求加密传输，请求体body封装测试
     *
     * @param
     * @return void
    */
    @Test
    public void postRequestBodyEncryptTest() throws Exception {
 
        //自定义方式获取 aesKey
        String aesKey = AESUtil.getAESKey(16);
        //内部方式获取 Base64AesKey
        String base64AesKey = AESUtil.generateRandomAesKeyWithBase64();
 
        //创建请求体body数据 content
        //模拟业务数据Json,并用AES密钥Key进行加密
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("id", 15);
        dataMap.put("name", "张三");
        dataMap.put("sex", "男");
        dataMap.put("age", 20);
        JSONObject dataJson = new JSONObject(dataMap);
        String contentJson = JSONObject.toJSONString(dataJson);
 
        //AES 加密业务数据
        String content = AESUtil.encryptToBase64(contentJson, aesKey);
        log.info("AES加密数据操作： \nAES加密之前的数据 = {} \nAES加密之后的数据 content= {}",contentJson,content);
 
        //RSA 加密AES密钥
        byte[] bytes = RSAUtil.encryptByPublicKey(aesKey.getBytes("UTF-8"), publicKey, RSAUtil.MAX_ENCRYPT_BLOCK);
        String encryptAesKey = RSAUtil.toHexString(bytes);
        log.info("RSA加密AES密钥操作： \nRSA加密之前的AES密钥= {} \nRSA加密之后的AES密钥 aesKey={}",aesKey,encryptAesKey);
 
        /**
         * 09:08:42.376 [main] INFO com.example.api_security_demo.utils.UtilsTestClass - AES加密数据操作：
         * AES加密之前的数据 = {"sex":"男","name":"张三","id":15,"age":20}
         * AES加密之后的数据 content= u/vRpwktLAo12ATyfa1rb14EHNftHfvhYEfy7r+DOJzO6jzXS4bwUJ0xNY8RJu8f
         * 09:08:42.380 [main] INFO com.example.api_security_demo.utils.UtilsTestClass - RSA加密AES密钥操作：
         * RSA加密之前的AES密钥= 9raG41FIE8uK7l3k
         * RSA加密之后的AES密钥 aesKey=c7eccef1d112075ee64eec65163b8b1dcb1a54ea6c8b51875174f6d34fc4ac7d50d2977b7519d275ee610d717d594228e132b053a70cdad9f925701a728ed794684d12097cfb8bea598c561393cb69de384b2ec83aa8ddb9a98a5adb3ed51ee1b9aaab2cf7bc5b49712a95e40ac4ea17421f5250d34b8e629e58db0b26e54b39
         * */
    }
 
    /**
     * Description: Get请求加密传输，请求体RequestParameter数据封装测试
     * 注意: 通过AES加密之后的数据 byte[] 需要转换为 HexString十六进制字符串后才能在 请求地址中传输，不能在用Base64编码格式的方式进行传输！
    */
    @Test
    public void getRequestBodyEncryptTest() throws Exception {
 
        //自定义方式获取 aesKey
        String aesKey = AESUtil.getAESKey(16);
        //内部方式获取 Base64AesKey
        String base64AesKey = AESUtil.generateRandomAesKeyWithBase64();
 
        //创建请求体body数据 content
        //模拟业务数据Json,并用AES密钥Key进行加密
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("id", 15);
        dataMap.put("name", "张三");
        dataMap.put("sex", "男");
        dataMap.put("age", 20);
        JSONObject dataJson = new JSONObject(dataMap);
        String contentJson = JSONObject.toJSONString(dataJson);
 
        //AES 加密业务数据
        byte[] contentByte = AESUtil.encrypt(contentJson.getBytes("UTF-8"), aesKey.getBytes("UTF-8"));
        String content = AESUtil.toHexString(contentByte);
        log.info("AES加密数据操作： \nAES加密之前的数据 = {} \nAES加密之后的Byte[]数据 = {}  \nAES加密后的数据转换为HexString十六进制字符串数据encryptData={}",contentJson,Arrays.toString(contentByte),content);
 
        //RSA 加密AES密钥
        byte[] bytes = RSAUtil.encryptByPublicKey(aesKey.getBytes("UTF-8"), publicKey, RSAUtil.MAX_ENCRYPT_BLOCK);
        String encryptAesKey = RSAUtil.toHexString(bytes);
        log.info("RSA加密AES密钥操作： \nRSA加密之前的AES密钥= {} \nRSA加密之后的AES密钥aesKey={}",aesKey,encryptAesKey);
 
        /**
         * 09:09:13.172 [main] INFO com.example.api_security_demo.utils.UtilsTestClass - AES加密数据操作：
         * AES加密之前的数据 = {"sex":"男","name":"张三","id":15,"age":20}
         * AES加密之后的Byte[]数据 = [73, 19, 107, 60, 29, 109, 100, 119, -81, -117, -84, -85, 19, 28, 86, 18, 123, 48, 58, 37, -28, -65, -93, -124, -50, 89, -10, -101, 48, 48, -104, -18, -109, 127, -19, 80, 62, -122, -80, -122, 94, 72, -16, -89, -1, -128, 22, -92]
         * AES加密后的数据转换为HexString十六进制字符串数据encryptData=49136b3c1d6d6477af8bacab131c56127b303a25e4bfa384ce59f69b303098ee937fed503e86b0865e48f0a7ff8016a4
         * 09:09:13.177 [main] INFO com.example.api_security_demo.utils.UtilsTestClass - RSA加密AES密钥操作：
         * RSA加密之前的AES密钥= 868E9FMA727S9W5q
         * RSA加密之后的AES密钥aesKey=2ab5531c7814201b4eaef3802ca883e79ffffd4c4ec32e698403189c0954718fd5cebd0ac5e66e856ec4f95a408442fc76276586a8fdb94c14c8f311f30ad061d6928315078736e6633113cdba255870a78e9077b2f18bdc4b2730804e5d6181df4b0ecf51597f71c8e0ccb89a5e160f1216a7bde5386b42171577db400d5a54
         * */
    }
 
 
    @Test
    public void testByteBase64String(){
 
        /*
         * 创建字节数组的方式
         * */
        byte[] testBytes = new byte[]{0,1,2,3,4};
        /*
         * 读取字节数组的方式：
         * */
        System.out.println("Arrays.toString(bytes1) = " + Arrays.toString(testBytes));
 
        //模拟业务数据Json,并用AES密钥Key进行加密
        Map<String, String> dataMap = new HashMap<>(2);
        dataMap.put("name", "张三");
        dataMap.put("age", "20");
        JSONObject dataJson = new JSONObject(dataMap);
        String jsonStr = JSONObject.toJSONString(dataJson);
 
        com.fasterxml.jackson.databind.ObjectMapper objectMapper = new com.fasterxml.jackson.databind.ObjectMapper();
        try {
            Map<String, Object> map = objectMapper.readValue(jsonStr, Map.class);
            System.out.println("map.toString() = " + map.toString());
            System.out.println("map.get(\"name\") = " + map.get("name"));
            System.out.println("map.get(\"age\") = " + map.get("age"));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
 
        byte[] jsonByte = dataJson.toString().getBytes();
        System.out.println("new String(jsonByte) = " + new String(jsonByte));
 
        //[两种方式不一样！]
        String hexStr = "0123456789abcdef";
        System.out.println("Arrays.toString(hexStr.getBytes()) = " + Arrays.toString(hexStr.getBytes()));
        System.out.println("Arrays.toString(RSAUtil.toBytes(hexStr)) = " + Arrays.toString(RSAUtil.toBytes(hexStr)));
    }
 
 
    /**
     * Description: 解密操作测试
    */
    @Test
    public void testAesDecrypt() throws Exception {
 
        String encryptAesKey = "868dbf00b6849a1189f186f18bc98eca65981829e12d3bad21f4a64c139a6fe6953729e488af642cb5bf7104459a4fbf084bb536f251e2d9fa39747037715da6a73caf23e1d68bd5338d51dd207ebe9c4a72749d87d73eb96fc193adac45e6b8b6b7fcc211ee47efd0d54ea97dcfdbc221ac0bd7664d32becbdd654c3d9b2446";
        String encryptDate = "8ee240b806a571f0f7ef5568d9cf5e36d999686acabfa4d5425d73ef7e546c8c1e9147c084269a6884cfeebf6759bd60";
 
        //解密之后的AesKey 56X8817GRC2p33w0
        byte[] decryptAesKey = RSAUtil.decryptByPrivateKey(RSAUtil.toBytes(encryptAesKey), privateKey, RSAUtil.MAX_DECRYPT_BLOCK);
        String decryptAesKeyStr = new String(decryptAesKey, "UTF-8");
        System.out.println("decryptAesKeyStr = " + decryptAesKeyStr);
 
        //GET请求数据解密 [加密数据为HexStr十六进制字符串形式]
        byte[] encryptDataByte = AESUtil.toBytes(encryptDate);
        System.out.println("Arrays.toString(encryptDataByte) 加密数据Byte[]形式 = " + Arrays.toString(encryptDataByte));
        String decryptData = new String(AESUtil.decrypt(encryptDataByte,decryptAesKeyStr.getBytes("UTF-8")),"UTF-8");
        System.out.println("decryptData解密后的数据 = " + decryptData);
 
      /*  //POST请求数据解密 [加密数据为Base64编码格式]
        String decryptData2 = AESUtil.decryptFromBase64(encryptDate, decryptAesKeyStr);
        System.out.println("decryptData2 解密后的数据 = " + decryptData2);*/
 
        /**
         * AES加密之前的数据 = {"sex":"男","name":"张三","id":15,"age":20}
         * AES加密之后的Byte[]数据 = [-114, -30, 64, -72, 6, -91, 113, -16, -9, -17, 85, 104, -39, -49, 94, 54, -39, -103, 104, 106, -54, -65, -92, -43, 66, 93, 115, -17, 126, 84, 108, -116, 30, -111, 71, -64, -124, 38, -102, 104, -124, -49, -18, -65, 103, 89, -67, 96]
         * AES加密后的数据转换为HexString十六进制字符串数据encryptData=8ee240b806a571f0f7ef5568d9cf5e36d999686acabfa4d5425d73ef7e546c8c1e9147c084269a6884cfeebf6759bd60
         * 16:48:25.095 [main] INFO com.example.api_security_demo.utils.UtilsTestClass - RSA加密AES密钥操作：
         * RSA加密之前的AES密钥= 8c0N9032214LJ139
         * RSA加密之后的AES密钥aesKey=868dbf00b6849a1189f186f18bc98eca65981829e12d3bad21f4a64c139a6fe6953729e488af642cb5bf7104459a4fbf084bb536f251e2d9fa39747037715da6a73caf23e1d68bd5338d51dd207ebe9c4a72749d87d73eb96fc193adac45e6b8b6b7fcc211ee47efd0d54ea97dcfdbc221ac0bd7664d32becbdd654c3d9b2446
         * */
    }
 
 
    /**
     * Description: 响应数据加密后，模拟前端进行解密操作
    */
    @Test
    public void responseEncryptToDecrypt() throws UnsupportedEncodingException {
        String aesKeyPost = "9raG41FIE8uK7l3k";
        String aesKeyGet = "0303F71572405EF1";
        String encryptData = "cf156ddc9cd9fde2a8287fa3b8eadca258ce063130d29d7d9c1b949a4628c42e497b4e1db76244bdd075cb37b8ef0212";
 
        //解密后的数据
        String decryptData = "";
        //Base64编码格式的数据解密
        //decryptData = AESUtil.decryptFromBase64(encryptData, aesKeyGet);
 
        //HexString格式的数据转换后在解密
        byte[] decrypt = AESUtil.decrypt(AESUtil.toBytes(encryptData), aesKeyGet.getBytes("UTF-8"));
        decryptData = new String(decrypt, "UTF-8");
 
        System.out.println("decryptData = " + decryptData);
    }
}